package com.easy.merchants.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CreateCache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easy.common.check.SVFilter;
import com.easy.common.core.domain.dto.UserDTO;
import com.easy.common.exception.CustomException;
import com.easy.common.utils.uuid.SnowFlake;
import com.easy.merchants.mapper.MerchantsMapper;
import com.easy.merchants.pojo.HouseFacility;
import com.easy.merchants.pojo.HouseImg;
import com.easy.merchants.pojo.HouseInformation;
import com.easy.merchants.pojo.dto.HouseDto;
import com.easy.merchants.service.HouseFacilityService;
import com.easy.merchants.service.HouseImgService;
import com.easy.merchants.service.MerchantsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.easy.common.utils.RedisConstants.HOUSE_CONTRACTION_KEY;

@Service
public class MerchantsServiceImpl extends ServiceImpl<MerchantsMapper, HouseInformation> implements MerchantsService {

    private static final Logger log = LoggerFactory.getLogger(MerchantsServiceImpl.class);

    //房屋图片信息表
    @Autowired
    private HouseImgService houseImgService;

    //设施表
    @Autowired
    private HouseFacilityService houseFacilityService;

    @Autowired
    private MerchantsMapper merchantsMapper;


    @CreateCache(area = "house", name = "info_", expire = 300, timeUnit = TimeUnit.SECONDS)
    private Cache<String, HouseDto> houseInfo;

    @Resource(name = "redisTemplateHouse")
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 获取房子详细信息
     *
     * @param id 房子id
     * @return {@link HouseDto}
     */
    @Transactional
    @Override
    public HouseDto getHouseDetailed(Long id) {
        HouseDto houseDto = null;
        try {
            LambdaQueryWrapper<HouseInformation> HouseInformationWrapper = new LambdaQueryWrapper<>();
            HouseInformationWrapper.eq(HouseInformation::getId, id);
            // 房子基本信息
            HouseInformation houseInformation = merchantsMapper.selectOne(HouseInformationWrapper);

            LambdaQueryWrapper<HouseImg> houseImgWrapper = new LambdaQueryWrapper<>();
            houseImgWrapper.eq(HouseImg::getRid, id);
            //房子图片信息
            HouseImg houseImg = houseImgService.getOne(houseImgWrapper);

            LambdaQueryWrapper<HouseFacility> HouseFacilityWrapper = new LambdaQueryWrapper<>();
            HouseFacilityWrapper.eq(HouseFacility::getRid, id);
            // 房子设施信息
            HouseFacility houseFacility = houseFacilityService.getOne(HouseFacilityWrapper);

            houseDto = new HouseDto();
            houseDto.setHouseImg(houseImg);
            houseDto.setHouseFacilities(houseFacility);
            BeanUtils.copyProperties(houseInformation, houseDto);
        } catch (Exception e) {
            throw new CustomException("获取房屋信息失败", "BC006");
        }
        return houseDto;
    }

    /**
     * 发布
     *
     * @param houseDto 房子dto
     */
    @Transactional
    @Override
    public void release(HouseDto houseDto) {
        String sv = svFilter.sv(houseDto.getTitle() + houseDto.getSummary());
        log.info("校验：{}", sv);
        // 若存在违规信息，审核跳为人工审核
        if (!sv.equals("合规")) {
            houseDto.setStatus("2");
            houseDto.setPermissions("1");
        }

        try {
            SnowFlake snowFlake = new SnowFlake(11, 1);
            long id = snowFlake.nextId();
            houseDto.setId(id);
            houseDto.setCreateTime(LocalDateTime.now());
            houseDto.setUpdateTime(LocalDateTime.now());
            // 1.保存基本信息
            this.save(houseDto);

            // 2.保存图片信息
            HouseImg houseImg = houseDto.getHouseImg();
            houseImg.setId(snowFlake.nextId());
            houseImg.setRid(id);
            houseImgService.save(houseImg);


            // 3.保存设施信息
            HouseFacility houseFacilities = houseDto.getHouseFacilities();
            houseFacilities.setId(snowFlake.nextId());
            houseFacilities.setRid(id);
            houseFacilityService.save(houseFacilities);

            // 4.缓存缩略信息
            HashMap<String, Object> houseMap = getHouseMap(houseDto);
            redisTemplate.opsForHash().putAll(HOUSE_CONTRACTION_KEY + id, houseMap);

        } catch (Exception e) {
            throw new CustomException("发布失败，请重新发布", "BC002");
        }

    }

    @Autowired
    private SVFilter svFilter;

    /**
     * 修改
     *
     * @param houseDto 房子dto
     */
    @Transactional
    @Override
    public void modify(HouseDto houseDto) {
        String msg = null;
        try {
            String sv = svFilter.sv(houseDto.getTitle() + houseDto.getSummary());
            if (!sv.equals("合规")) {
                msg = sv;
                throw new CustomException();
            }
            houseDto.setUpdateTime(LocalDateTime.now());
            // 1.修改房屋基本信息
            this.updateById(houseDto);

            // 2.修改房屋图片信息
            HouseImg houseImg = houseDto.getHouseImg();
            boolean flag = houseImgService.updateImgByRid(houseImg);
            if (!flag) {
                msg = "修改房屋信息失败，请重新修改";
                throw new CustomException();
            }

            // 3.修改房屋设施信息
            HouseFacility houseFacilities = houseDto.getHouseFacilities();
            boolean flag2 = houseFacilityService.updateHouseFacilityByRid(houseFacilities);
            log.info("修改房屋信息:{}", flag2);
            if (!flag2) {
                msg = "修改房屋信息失败，请重新修改";
                throw new CustomException();
            }
            // 4.删除房屋详细信息缓存
            houseInfo.remove(String.valueOf(houseDto.getId()));

            // 5.删除房屋缩略信息缓存
//            Long delete = redisTemplate.opsForHash().delete(HOUSE_CONTRACTION_KEY + houseDto.getId());

            // 6.更新房屋缩略信息缓存
            HashMap<String, Object> houseMap = getHouseMap(houseDto);
            redisTemplate.opsForHash().putAll(HOUSE_CONTRACTION_KEY + houseDto.getId(), houseMap);

        } catch (Exception e) {
            throw new CustomException(msg, "BC003");
        }
    }

    /**
     * 逻辑删除
     *
     * @param id id
     */
    @Override
    public void delete(Long id) {
        try {
            LambdaUpdateWrapper<HouseInformation> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(HouseInformation::getId, id);
            wrapper.set(HouseInformation::getDeletedFlag, "1");
            this.update(wrapper);
            houseInfo.remove(String.valueOf(id));

            HashMap<String, Object> houseMap = new HashMap<>();
            houseMap.put("deletedFlag", "1");
            // 6.更新房屋缩略信息缓存
            redisTemplate.opsForHash().putAll(HOUSE_CONTRACTION_KEY + id, houseMap);

        } catch (Exception e) {
            throw new CustomException("删除失败，请重新删除", "BC004");
        }
    }

    /**
     * 物理删除
     *
     * @param id id
     */
    @Transactional
    @Override
    public void physicalDeletion(Long id) {

        try {
            // 1.删除房屋信息
            merchantsMapper.deleteHouseInformationById(id);
            // 2.删除房子图片
            merchantsMapper.deleteHouseImgById(id);
            // 3.删除房屋设施
            merchantsMapper.deleteHouseFacilityById(id);
            houseInfo.remove(String.valueOf(id));

            HashMap<String, Object> houseMap = new HashMap<>();
            houseMap.put("deletedFlag", "-1");
            // 6.更新房屋缩略信息缓存
            redisTemplate.opsForHash().putAll(HOUSE_CONTRACTION_KEY + id, houseMap);
        } catch (Exception e) {
            throw new CustomException("删除失败，请重新删除", "BC005");
        }

    }

    /**
     * 起售 停售
     *
     * @param houseInformation 房子信息dto
     */
    @Override
    public void startAndStop(HouseInformation houseInformation) {
        int row = merchantsMapper.updateHouseStatus(houseInformation);
        if (row <= 0) {
            throw new CustomException("参数信息有误", "CA003");
        }
        houseInfo.remove(String.valueOf(houseInformation.getId()));
    }

    private HashMap<String, Object> getHouseMap(HouseDto houseDto) {
        HashMap<String, Object> houseMap = new HashMap<>();
        houseMap.put("title", houseDto.getTitle());
        houseMap.put("img", houseDto.getImg());
        houseMap.put("price", houseDto.getPrice());
        houseMap.put("areaSize", houseDto.getAreaSize());
        houseMap.put("status", houseDto.getStatus());
        houseMap.put("deletedFlag", houseDto.getDeletedFlag());
        return houseMap;
    }
}
